package com.usd.utils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

public class Myutils {
	public static <T> T assignBean(HttpServletRequest res, Class<T> clazz) {
		// 得到传来反射类的对象
		T t = getInstence(clazz);
		if (res != null) {
			/*******
			 * 注册定义了类型转换器：form表单中的String串向目标数据类型的自定义转换 如果传入的
			 * 定义BeanUtils的包装类类型的转换器【可以使用匿名内部类】
			 ********/
			// 碰到Date类型将其转换为String类型
			// BeanUtils.setProperty第二个参数碰到为Date类型，将要赋进去的值转为Date类型
			// BeanUtils.setProperty支持八大类型转换，包括Date一些的类型需要支持单独注册
			ConvertUtils.register(new Myconverter(), Date.class);
			// 获取request中提交所有的表单控件的name属性值
			Enumeration<String> emn = res.getParameterNames();
			if (emn != null) {
				try {
					while (emn.hasMoreElements()) {
						// 获取下一个name属性值
						String strName = emn.nextElement();
						// 获取当前name属性对应的value值
						String strValue = res.getParameter(strName);
						// 使用反射将表单的value值设置到与之对应的实体类属性中【借助beanutils或者直接使用反射】
						//
						BeanUtils.setProperty(t, strName, strValue);
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				///////////////////// 文件的映射处理-begin////////////////////////////
				// 从request中将文件流信息进行提取，将其保存到服务器指定目录，并将保存的目录的相对地址存入数据库中
				// 判断http头中是否含有上传头文件备注（multipart/form-data）
				if (res.getContentType().split(";")[0].equals("multipart/form-data")) {
					try {
						// 获取request中的所有的控件的part集合【每个part中包含form表单中的一个控件对象】
						Collection<Part> parts = res.getParts();
						// 遍历每一个part，处理含有文件的part部分
						// 检查含有文件流的part部分进行处理
						for (Part part : parts) {
							// 使用part的ContentType来区分该part是包含文件流控件还是普通控件
							// 获取 MINE类型，普通控件的改属性是 null，文件上传控件的属性不是null
							// 判断获取的文件大小是否大于0
							String partContent = part.getContentType();
							System.out.println((part != null) + "" + (part.equals("")) + part.getSize());
							if (partContent != null && !partContent.equals("") && part.getSize() > 0) {
								// 处理含有文件流空间的part，进行文件上传
								// 准备文件上传的服务器的路径地址【要求是绝对地址】
								String fileUrl = res.getServletContext().getRealPath("/");
								System.out.println(fileUrl + "///");
								// 规定：默认存储在 static/uploadfiles/
								String strUploadPath = fileUrl;
								// 文件上传时保存的相对路径地址
								String strRelativePath = "static/uploadfiles/uploadDerictory";
								System.out.println(strUploadPath + strRelativePath);
								// 检测文件上传目录是否已经存在，如果不存在，则创建
								File file = new File(strUploadPath + strRelativePath);
								if (!file.exists()) {
									// 建造相应目录文件
									file.mkdirs();
								}
								// 获取包含文件后缀信息的上下文的字符描述串
								String strContent = part.getHeader("Content-Disposition");
								// 正则表达式匹配文件后缀
								String strReg = "\\.\\w*";
								// 创建正则表达式类
								Pattern pat = Pattern.compile(strReg);
								// 将要匹配的字符串插入此对象进行比较操作
								Matcher mat = pat.matcher(strContent);
								// 进行子字符串匹配，如果要寻找的字字符串在内就为true进入循环
								// 设置默认保存文件的格式
								String fileType = ".dat";
								if (mat.find()) {
									// 第0组的完全匹配
									fileType = mat.group(0);
								}
								// 组合一个具有随机码的文件名
								String fileName = "userImg_" + System.currentTimeMillis() + fileType;
								System.out.println(fileUrl + File.separatorChar + fileName);
								// 上传文件至服务器保存路径
								part.write(strUploadPath + strRelativePath + File.separatorChar + fileName);
								// 将文件的相对路径保存到文件的实体类属性中
								// 获取文件上传控件的name属性
								String inputName = part.getName();
								try {
									// 将保存在服务器的文件地址赋值给数据库保存
									// 保存至数据库的服务器图片地址必须是相对于服务器的相对地址【重要！！！！！】
									BeanUtils.setProperty(t, inputName,
											strRelativePath + File.separatorChar + fileName);
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							} else {

							}
						}

					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (ServletException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

			}

		}
		return t;

	}

	/**
	 * 将时间类型专为制定格式的字符串【转换失败返回null】
	 * 
	 * @param date
	 *            被转化的时间对象
	 * @param strDatePattern
	 *            转换的时间格式串
	 * @return 转换之后的日期字符串
	 */
	public static String convertDate2String(Date date, String strDatePattern) {
		// 返回值
		String strDate = null;

		// 日期格式串检测
		if (strDatePattern == null || strDatePattern.equals("")) {
			// 给定默认的时间格式串
			strDatePattern = "yyyy-MM-dd HH:mm:ss";
		}

		// 创建日期转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strDatePattern);

		if (date != null) {
			// 将日期类型专为指定格式的字符串
			strDate = sdf.format(date);
		} else {
			// 根据需求确定
			// strDate = sdf.format(new Date());
		}
		// 返回值
		return strDate;
	}

	/**
	 * 将字符串转换为日期对象 【注意：日期格式串和日期字符串要在格式上匹配】
	 * 
	 * @param strDate
	 *            日期字符串
	 * @param strDatePattern
	 *            日期格式串
	 * @return 转换之后的日期对象【默认为当前系统时间】
	 */
	public static Date convertString2Date(String strDate, String strDatePattern) {
		// 返回值，默认为当前时间【还是为null，根据业务需求定】
		Date date = new Date();
		// 日期格式串检测:注意：日期格式串和日期字符串要在格式上匹配
		if (strDatePattern == null || strDatePattern.equals("")) {
			// 给定默认的时间格式串
			strDatePattern = "yyyy-MM-dd HH:mm:ss";
		}

		// 创建日期转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strDatePattern);

		try {
			// 进行日期转换
			date = sdf.parse(strDate);
		} catch (Exception e) {
			// 日期转换异常
			System.out.println("字符串转为日期对象异常：" + e.getMessage());
			e.printStackTrace();
		}
		// 返回值
		return date;
	}

	public static <T> T getInstence(Class<T> clazz) {
		T t = null;
		try {
			// 创建该反射类的对象
			t = clazz.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 返回该clazz的实例对象
		return t;

	}
}
